package models

import (
	"fmt"

	"encoding/json"
	"github.com/dailing/levlog"
)

type Jsontype map[string]interface{}

func NewJsonFile() Jsontype {
	return make(map[string]interface{})
}

func ParseJson(str string) Jsontype {
	j := NewJsonFile()
	err := json.Unmarshal([]byte(str), &j)
	if err != nil {
		levlog.E(err)
		return nil
	}
	return j
}

func (j Jsontype) Clone() Jsontype {
	return ParseJson(j.ToString())
}

func (j Jsontype) ToString() string {
	data, err := json.Marshal(j)
	if err != nil {
		levlog.Error(err)
		return ""
	}
	return string(data)
}

func (j Jsontype) Set(key string, val interface{}) Jsontype {
	j[key] = val
	return j
}

func (j Jsontype) Append(key string, val interface{}) Jsontype {
	if _, found := j[key]; found == true {
		if inst, ok := j[key].([]interface{}); ok == true {
			inst = append(inst, val)
			j[key] = inst
			return j
		}
		levlog.Error("ERROR APPEND TYPE")
		return j
	}
	arr := make([]interface{}, 1)
	arr[0] = val
	j[key] = arr
	return j
}

func (j Jsontype) ReadString(key string) string {
	if inst, ok := j[key]; ok == true {
		return fmt.Sprint(inst)
	}
	levlog.Error("No such key : ", key)
	return ""
}

func (j Jsontype) ReadStringWithDefault(key string, def string) string {
	if j.HasKey(key) {
		return j.ReadString(key)
	}
	return def
}

func (j Jsontype) ReadInt(key string) int {
	if inst, ok := j[key]; ok == true {
		if inst2, ok2 := inst.(int); ok2 == true {
			return inst2
		}
		if inst2, ok2 := inst.(float64); ok2 == true {
			return int(inst2)
		}
		if inst2, ok2 := inst.(int8); ok2 == true {
			return int(inst2)
		}
		if inst2, ok2 := inst.(int16); ok2 == true {
			return int(inst2)
		}
		if inst2, ok2 := inst.(int32); ok2 == true {
			return int(inst2)
		}
		if inst2, ok2 := inst.(int64); ok2 == true {
			return int(inst2)
		}
		if inst2, ok2 := inst.(uint); ok2 == true {
			return int(inst2)
		}
		levlog.Error("Type Not Match for key ", key)
	}
	levlog.Error("Key ", key, " Not Found")
	return 0
}

func (j Jsontype) ReadFloat(key string) float64 {
	if inst, ok := j[key]; ok == true {
		if inst2, ok2 := inst.(float64); ok2 == true {
			return inst2
		}
		if inst2, ok2 := inst.(float32); ok2 == true {
			return float64(inst2)
		}
		if inst2, ok2 := inst.(int8); ok2 == true {
			return float64(inst2)
		}
		if inst2, ok2 := inst.(int16); ok2 == true {
			return float64(inst2)
		}
		if inst2, ok2 := inst.(int32); ok2 == true {
			return float64(inst2)
		}
		if inst2, ok2 := inst.(int64); ok2 == true {
			return float64(inst2)
		}
		if inst2, ok2 := inst.(uint); ok2 == true {
			return float64(inst2)
		}
		levlog.Error("Type Not Match for key ", key)
	}
	levlog.Error("Key ", key, " Not Found")
	return 0
}

func (j Jsontype) ReadIntWithDefault(key string, def int) int {
	if j.HasKey(key) {
		return j.ReadInt(key)
	}
	return def
}

func (j Jsontype) ReadObject(key string) Jsontype {
	if inst, ok := j[key]; ok {
		if inst2, ok2 := inst.(map[string]interface{}); ok2 {
			return inst2
		}
		if inst2, ok2 := inst.(Jsontype); ok2 {
			return inst2
		}
		levlog.Error("Type Error for key : ", key)
		return nil
	}
	levlog.Error("No such key ", key)
	return nil
}

func (j Jsontype) HasKey(key string) bool {
	_, ok := j[key]
	return ok
}
